﻿using System;
using System.Reflection;
using System.Reflection.Emit;

namespace Rocky
{
#if DEBUG
    public interface ITest
    {
        string Wow(string str);
    }

#endif
    public class UnitTest
    {
        public static void TestEmitInterface()
        {
            var assName = new AssemblyName("TestEmitInterface");
            AssemblyBuilder assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName,
                                                                                       AssemblyBuilderAccess.Run);
            ModuleBuilder modBuilder = assBuilder.DefineDynamicModule(assBuilder.GetName().Name);
            TypeBuilder typeBuilder = modBuilder.DefineType("TestEmitInterface.TestImpl", TypeAttributes.Public);
            typeBuilder.AddInterfaceImplementation(typeof (ITest));

            var ctor = new MethodGenerator(typeBuilder, "ctor", MethodAttributes.Public, CallingConventions.Standard,
                                           null, Type.EmptyTypes);
            ctor.Ldarg(0);
            ctor.Call(typeof (object).GetConstructor(Type.EmptyTypes));
            ctor.Ret();

            MethodInfo mi = typeof (ITest).GetMethod("Wow");

            var wow = new MethodGenerator(typeBuilder, mi.Name,
                                          mi.Attributes & (~MethodAttributes.Abstract) | MethodAttributes.Public,
                                          mi.CallingConvention, mi.ReturnType, new[] {typeof (string)});
            wow.Ldarg(1);
            wow.Ret();

            typeBuilder.DefineMethodOverride(wow.CurrentMethod, mi);

            Type testImplType = typeBuilder.CreateType();
            var test = (ITest) Activator.CreateInstance(testImplType);

            Console.WriteLine(test.Wow("hello") == "hello");
        }
    }
}